module;

#include <print>

#include <asio.hpp>
// https://think-async.com/Asio/asio-1.30.2/doc/asio/overview/composition/coro.html
#include <asio/experimental/coro.hpp>
// coro的co_spawn
// 在源码的单元测试中可以发现
#include <asio/experimental/co_spawn.hpp>

export module main;

using namespace asio;
using namespace asio::experimental;

coro<int, int> c(io_context &ctx)
{
    // auto x = c(ctx);
    // co_await x;
    co_yield 1;
    co_return 42;
}

coro<void> c1(io_context &ctx)
{
    auto v = c(ctx);
    // 返回类型就是 int,由以下特性决定
    // template <typename YieldReturn>
    // struct coro_result<YieldReturn, YieldReturn>
    // {
    //   using type = YieldReturn;
    // };
    auto r = co_await v;
    std::print("{} ", r);
    std::print("{} ", co_await v);
    // r结束了,继续调用,产生段错误
    // std::print("{} ", co_await v);

    // 如果c的函数返回值的签名是coro<double, int>,则co_await v返回的是一个std::variant<double, int>
}

// 不能放到awitable中,只能放到coro中
awaitable<void> c2(io_context &ctx)
{
    auto v = c(ctx);
    // 不能放到awitable中,只能放到coro中
    // https://think-async.com/Asio/asio-1.30.2/doc/asio/overview/composition/coro.html
    // 在awaitable中只能用这种方式
    int x = co_await v.async_resume(use_awaitable);
    // 而不能直接
    //  int x = co_await v;
    co_return;
}

int main()
{
    asio::io_context ctx;
    asio::experimental::co_spawn(c1(ctx), detached);
    // asio::experimental::co_spawn(c1(ctx), [](auto && ...){});
    // asio::experimental::co_spawn(c1(ctx), [](auto &&){});
    ctx.run();
    return 0;
}
